from machine import reset, Pin
from time import sleep, ticks_ms
import usocket as socket
import gc
import camera
import network
import _thread

# ==================== 配置参数 ====================
WIFI_SSID = "LAPTOP-D3RPTUAA 6358"
WIFI_PASSWORD = "19234949992.ch"
CAMERA_FRAMESIZE = 9  # 640x480 
CAMERA_QUALITY = 15   # 图像质量 (0-63，值越大质量越低)
REFRESH_INTERVAL = 1000  # 网页刷新间隔(毫秒)
DEBUG = True

# ==================== 摄像头硬件配置（引脚顺序必须严格对应） ====================
# 按 camera.init() 的位置参数顺序定义引脚：
# 顺序：pwdn, reset, xclk, sccb_sda, sccb_scl, d7, d6, d5, d4, d3, d2, d1, d0, vsync, href, pclk
CAMERA_PIN_ORDER = [
    ('pwdn', 32),
    ('reset', -1),
    ('xclk', 0),
    ('sccb_sda', 26),
    ('sccb_scl', 27),
    ('d7', 35),
    ('d6', 34),
    ('d5', 39),
    ('d4', 36),
    ('d3', 21),
    ('d2', 19),
    ('d1', 18),
    ('d0', 5),
    ('vsync', 25),
    ('href', 23),
    ('pclk', 22),
]

# ==================== 全局变量 ====================
latest_frame = None  
frame_lock = _thread.allocate_lock()  

# ==================== WiFi连接 ====================
def connect_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print(f"连接WiFi: {ssid}")
        wlan.connect(ssid, password)
        for _ in range(30):
            if wlan.isconnected():
                break
            sleep(1)
            print("等待连接...")
        if not wlan.isconnected():
            print("WiFi连接失败")
            return None
    ip_address = wlan.ifconfig()[0]
    print(f"WiFi连接成功，IP地址: {ip_address}")
    return ip_address

# ==================== 摄像头初始化（位置参数修复版） ====================
def init_camera():
    """严格按位置参数初始化摄像头，适配旧版MicroPython"""
    try:
        # 位置参数调用 camera.init()
        camera.init()
        
        # 配置摄像头参数
        camera.framesize(CAMERA_FRAMESIZE)
        camera.quality(CAMERA_QUALITY)
        camera.brightness(0)
        camera.contrast(0)
        camera.saturation(0)
        camera.flip(1)
        camera.mirror(0)
        print("摄像头初始化完成")
        return True
    except Exception as e:
        print(f"摄像头初始化错误: {e}")
        return False

# ==================== 图像捕获线程 ====================
def capture_thread():
    global latest_frame, frame_lock
    while True:
        try:
            start_time = ticks_ms()
            frame = camera.capture()
            if frame and len(frame) > 1024:
                with frame_lock:
                    latest_frame = frame
                if DEBUG:
                    print(f"捕获图像: {len(frame)}字节，耗时: {ticks_ms() - start_time}ms")
            sleep(REFRESH_INTERVAL / 1000)
        except Exception as e:
            print(f"图像捕获错误: {e}")
            camera.deinit()
            sleep(1)
            init_camera()
        gc.collect()

# ==================== HTTP服务器 ====================
def handle_client(client_sock):
    global latest_frame, frame_lock
    try:
        request = client_sock.recv(1024).decode()
        if not request:
            return
        path = request.split(' ')[1]
        if DEBUG:
            print(f"收到请求: {path}")
        
        if path == '/':
            html = f"""
                    <!DOCTYPE html>
                    <html>
                    <head>
                        <title>ESP32-CAM 实时画面</title>
                        <meta name="viewport" content="width=device-width, initial-scale=1.0">
                        <style>
                            body {{ 
                                font-family: Arial, sans-serif; 
                                margin: 0; 
                                padding: 20px; 
                                background-color: #f5f5f5;
                            }}
                            .container {{ 
                                max-width: 1000px; 
                                margin: 0 auto; 
                            }}
                            h1 {{ 
                                color: #333; 
                                text-align: center;
                            }}
                            #stream-container {{ 
                                background-color: #000; 
                                border-radius: 8px; 
                                overflow: hidden;
                                box-shadow: 0 4px 8px rgba(0,0,0,0.2);
                            }}
                            #live-stream {{ 
                                width: 100%; 
                                height: auto;
                            }}
                            .status {{ 
                                text-align: center; 
                                margin-top: 10px; 
                                color: #666;
                            }}
                        </style>
                    </head>
                    <body>
                        <div class="container">
                            <h1>ESP32-CAM 实时流</h1>
                            <div id="stream-container">
                                <img id="live-stream" src="" alt="实时摄像头画面">
                            </div>
                            <div class="status">刷新间隔: {REFRESH_INTERVAL}ms</div>
                        </div>
                        
                        <script>
                            const img = document.getElementById('live-stream');
                            const statusElem = document.querySelector('.status');
                            let errorCount = 0;
                            
                            function updateImage() {{
                                img.src = "/image?" + new Date().getTime();
                                
                                img.onload = function() {{
                                    errorCount = 0;
                                    statusElem.textContent = "正常 - 最后更新: " + new Date().toLocaleTimeString();
                                }};
                                
                                img.onerror = function() {{
                                    errorCount++;
                                    statusElem.textContent = "错误 (" + errorCount + ") - 尝试重新加载...";
                                    if (errorCount >= 5) {{
                                        window.location.reload();
                                    }}
                                }};
                            }}
                            
                            updateImage();
                            setInterval(updateImage, {REFRESH_INTERVAL});
                        </script>
                    </body>
                    </html>
                    """
            response = f"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {len(html)}\r\n\r\n{html}"
            client_sock.send(response.encode())
        
        elif path.startswith('/image'):
            with frame_lock:
                if latest_frame:
                    response = f"HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: {len(latest_frame)}\r\n\r\n"
                    client_sock.send(response.encode() + latest_frame)
                else:
                    client_sock.send("HTTP/1.1 503 Service Unavailable\r\n\r\nNo image data".encode())
        
        else:
            client_sock.send("HTTP/1.1 404 Not Found\r\n\r\nPage not found".encode())
            
    except Exception as e:
        if DEBUG:
            print(f"处理请求错误: {e}")
    finally:
        client_sock.close()

def start_http_server(ip):
    server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_sock.bind((ip, 80))
    server_sock.listen(1)
    print(f"HTTP服务器已启动，请在浏览器访问: http://{ip}")
    while True:
        client_sock, client_addr = server_sock.accept()
        if DEBUG:
            print(f"新连接: {client_addr}")
        handle_client(client_sock)

# ==================== 主函数 ====================
def main():
    gc.enable()
    print("ESP32-CAM 启动中...")
    
    # 初始化摄像头（修复后）
    if not init_camera():
        print("摄像头初始化失败，重启设备...")
        reset()
    
    ip_address = connect_wifi(WIFI_SSID, WIFI_PASSWORD)
    if not ip_address:
        print("WiFi连接失败，重启设备...")
        reset()
    
    _thread.start_new_thread(capture_thread, ())
    start_http_server(ip_address)

if __name__ == "__main__":
    main()